package co.edu.unal.geditor.view;

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.Toolkit;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.util.Map;
import java.util.ResourceBundle;

import javax.swing.ButtonGroup;
import javax.swing.JButton;
import javax.swing.JCheckBoxMenuItem;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JSeparator;
import javax.swing.JToggleButton;
import javax.swing.JToolBar;

import co.edu.unal.geditor.controller.App;
import co.edu.unal.geditor.controller.action.edit.ChangeFontAction;
import co.edu.unal.geditor.controller.action.edit.Delete;
import co.edu.unal.geditor.controller.action.edit.EditRedo;
import co.edu.unal.geditor.controller.action.edit.EditUndo;
import co.edu.unal.geditor.controller.action.edit.color.ChangeBackgroundColorAction;
import co.edu.unal.geditor.controller.action.edit.color.ChangeFillingColorAction;
import co.edu.unal.geditor.controller.action.edit.color.ChangeLinesColorAction;
import co.edu.unal.geditor.controller.action.file.FileExit;
import co.edu.unal.geditor.controller.action.file.FileNew;
import co.edu.unal.geditor.controller.action.file.FileOpen;
import co.edu.unal.geditor.controller.action.file.FileSave;
import co.edu.unal.geditor.controller.action.file.FileSaveAs;
import co.edu.unal.geditor.model.ClosedGraphElement;
import co.edu.unal.geditor.model.DrawingListener;
import co.edu.unal.geditor.model.GraphElement;
import co.edu.unal.geditor.view.tools.Tool;
import co.edu.unal.geditor.view.tools.ToolFactory;

public class MainFrame extends JFrame implements DrawingListener {
	private static final long serialVersionUID = 1L;

	public MainFrame() {

		setDefaultSize();

		// new in v0.8
		loadTools();
		// new in v0.8
		// m_linesColorButton.
		// add an empty menu bar
		addMainMenu();

		// add an empty tool bar
		addToolBar();

		// add a status bar
		addStatusBar();

		// add the canvas
		addCanvas();

		addColorBar();
		// give App a chance to do clean up before exiting
		setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);

		// Observer + Adapter design patterns
		addWindowListener(new WindowAdapter() {
			@Override
			public void windowClosing(WindowEvent e) {
				App.getInstance().exit();
			}
		});

	}

	// new in v0.8
	private void loadTools() {
		
		ResourceBundle RESOURCE_BUNDLE = ResourceBundle
				.getBundle("co.edu.unal.geditor.view.tools.BasicTools");
		for (String s : RESOURCE_BUNDLE.keySet()) {
			try {
				Class.forName(RESOURCE_BUNDLE.getString(s));
			} catch (ClassNotFoundException exc) {
				exc.printStackTrace();
			}
		}
	}

	// new in v0.8

	public void init() {
		assert m_canvas != null;

		m_canvas.init();

		setActiveTool(ToolFactory.getDefaultTool());
		App.getInstance().getDrawing().addListener(this);
	}

	private void setDefaultSize() {
		Toolkit t = Toolkit.getDefaultToolkit();
		Dimension ss = t.getScreenSize();

		setBounds((ss.width - DEF_WIDTH) / 2, (ss.height - DEF_HEIGHT) / 2,
				DEF_WIDTH, DEF_HEIGHT);
	}

	private void addMainMenu() {
		JMenuBar mbar = new JMenuBar();

		JMenu fileMenu = new JMenu("File");
		fileMenu.add(new FileNew());
		fileMenu.add(new JSeparator());
		fileMenu.add(new FileOpen());
		fileMenu.add(new FileSave());
		fileMenu.add(new FileSaveAs());
		fileMenu.add(new JSeparator());
		fileMenu.add(new FileExit());
		mbar.add(fileMenu);

		// new in v0.8
		m_miUndo = new JMenuItem(new EditUndo());
		m_miRedo = new JMenuItem(new EditRedo());

		JMenu editMenu = new JMenu("Edit");
		editMenu.add(m_miUndo);
		editMenu.add(m_miRedo);
		editMenu.add(new Delete());
		mbar.add(editMenu);

		m_toolMenu = new JMenu("Tool");

		// new in v0.8
		Map<String, Tool> ht = ToolFactory.getToolSet();
		for (Tool t : ht.values()) {
			m_toolMenu.add(new JCheckBoxMenuItem(t.getAction()));
		}
		// new in v0.8

		// add all menu items to a multiple-exclusion group
		ButtonGroup group = new ButtonGroup();
		for (int i = 0; i < m_toolMenu.getItemCount(); i++) {
			group.add(m_toolMenu.getItem(i));
		}
		mbar.add(m_toolMenu);

		mbar.add(new JMenu("View"));
		mbar.add(new JMenu("Help"));

		add(mbar, BorderLayout.NORTH);
	}

	private void addToolBar() {
		m_toolBar = new JToolBar(JToolBar.VERTICAL);
		m_toolBar.setFloatable(true);

		// new in v0.8
		Map<String, Tool> ht = ToolFactory.getToolSet();
		for (Tool t : ht.values()) {
			m_toolBar.add(new JToggleButton(t.getAction()));
		}
		// new in v0.8

		// add all menu items to a multiple-exclusion group
		ButtonGroup group = new ButtonGroup();
		for (int i = 0; i < m_toolBar.getComponentCount(); i++) {
			group.add((JToggleButton) m_toolBar.getComponent(i));
		}

		add(m_toolBar, BorderLayout.WEST);
	}

	private void addStatusBar() {
		m_statusBar = new StatusBar();

		add(m_statusBar, BorderLayout.SOUTH);
	}

	private void addColorBar() {
		m_colorBar = new JToolBar(JToolBar.VERTICAL);
		m_colorBar.setFloatable(true);

		m_backgroundColorButton = new JButton(new ChangeBackgroundColorAction());
		m_fillingColorButton = new JButton(new ChangeFillingColorAction());
		m_linesColorButton = new JButton(new ChangeLinesColorAction());
		JButton m_fontButton = new JButton(new ChangeFontAction());

		m_colorBar.add(m_backgroundColorButton);
		m_colorBar.add(m_fillingColorButton);
		m_colorBar.add(m_linesColorButton);
		m_colorBar.add(m_fontButton);
		add(m_colorBar, BorderLayout.EAST);
		setColorButtons();
	}

	private void setColorButtons() {

		m_backgroundColorButton.setBackground(m_canvas.getBackground());
		m_fillingColorButton.setBackground(ClosedGraphElement
				.getDefaultFillingColor());
		m_linesColorButton.setBackground(GraphElement.getDefaultLinesColor());

	}

	public void setStatus(String msg) {
		assert m_statusBar != null;
		assert msg != null;

		m_statusBar.setMsg(msg);
	}

	private void addCanvas() {
		m_canvas = new Canvas();

		add(m_canvas, BorderLayout.CENTER);
	}

	// set active tool (collaboration: Canvas)
	// PRE-CONDITION: tool != null
	// POST-CONDITION: active tool changed
	public void setActiveTool(Tool tool) {
		assert tool != null;
		App.getInstance().getDrawing().deSelectAll();

		for (int i = 0; i < m_toolMenu.getItemCount(); i++) {
			JMenuItem mi = m_toolMenu.getItem(i);
			if (mi.getAction() == tool.getAction()) {
				mi.setSelected(true); // check the check-box
				break;
			}
		}
		for (int i = 0; i < m_toolBar.getComponentCount(); i++) {
			JToggleButton button = (JToggleButton) m_toolBar.getComponent(i);
			if (button.getAction() == tool.getAction()) {
				button.setSelected(true); // press the button
				button.requestFocus();
				break;
			}
		}
		tool.setActiveFeedbackGraphElement();
		m_canvas.setActiveTool(tool);
		m_canvas.update();

	}

	public Canvas getCanvas() {
		return m_canvas;
	}

	// new in v0.8
	public void setUndoText(String sTxt) {
		m_miUndo.setText(sTxt);
	}

	public void setUndoEnabled(boolean b) {
		m_miUndo.setEnabled(b);
	}

	public void setRedoText(String sTxt) {
		m_miRedo.setText(sTxt);
	}

	public void setRedoEnabled(boolean b) {
		m_miRedo.setEnabled(b);
	}

	public void processDrawingEvent(DrawingEvent de) {
		setColorButtons();
		m_colorBar.repaint();

	}

	// new in v0.8

	private Canvas m_canvas;
	private JMenu m_toolMenu;
	private JToolBar m_toolBar;
	private StatusBar m_statusBar;
	private JToolBar m_colorBar;

	// new in v0.8
	private JMenuItem m_miUndo;
	private JMenuItem m_miRedo;
	// new in v0.8

	public static final int DEF_WIDTH = 800;
	public static final int DEF_HEIGHT = 600;

	protected JButton m_backgroundColorButton;
	protected JButton m_fillingColorButton;
	protected JButton m_linesColorButton;

}
